home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue44 / HTMLmove / Spritebx.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1997-08-28  |  8.4 KB  |  305 lines

  1. { *****************************************************
  2.                          TSpriteBox Component
  3.  
  4.   TSpriteBox is a TCustomControl derivative which has 2 offscreen
  5.   bitmaps for sprite animation.
  6.  
  7.   TSpriteBox is designed to work with TSprite. Drop a TSprite 
  8.   on the form and watch it go!
  9.  
  10.                   Paul Warren
  11.          HomeGrown Software Development
  12.        (c) 1996 Langley British Columbia.
  13.                 (604) 530-9097
  14.          e-mail:  hg_soft@uniserve.com
  15.     Home page: http://haven.uniserve.com/~hg_soft
  16.   ***************************************************** }
  17.  
  18. unit Spritebx;
  19.  
  20. interface
  21.  
  22. uses
  23.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  24.   Forms, Dialogs, StdCtrls, ExtCtrls, Sprites;
  25.  
  26. type
  27.   TSpriteBox = class(TCustomControl)
  28.   private
  29.     { private declarations }
  30.     FImage: TBitMap;
  31.     FBackGnd1: TBitMap;
  32.     FBackGnd2: TBitMap;
  33.     FColor: TColor;
  34.     FCenter: boolean;
  35.     FStretch: boolean;
  36.     FGradient: boolean;
  37.     FBeforeSprtMove: TNotifyEvent;
  38.     FAfterSprtMove: TNotifyEvent;
  39.     procedure SetImage(AImage: TBitmap);
  40.     procedure SetColor(Value: TColor);
  41.     procedure SetCenter(Value: boolean);
  42.     procedure SetStretch(Value: boolean);
  43.     procedure SetGradient(Value: boolean);
  44.     procedure SetBeforeSprtMove(Value: TNotifyEvent);
  45.     procedure SetAfterSprtMove(Value: TNotifyEvent);
  46.     procedure Loaded; override;
  47.     procedure GradientFill(Color1, Color2: TColor);
  48.     procedure DrawBMP;
  49.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  50.   protected
  51.     { protected declarations }
  52.     function GetPalette: HPALETTE; override;
  53.     procedure HasChanged(Sender: TObject);
  54.     procedure Paint; override;
  55.   public
  56.     { public declarations }
  57.     constructor Create(AOwner: TComponent); override;
  58.     destructor Destroy; override;
  59.     procedure DrawSprite;
  60.     property BackGnd1: TBitmap read FBackGnd1 write FBackGnd1;
  61.     property BackGnd2: TBitmap read FBackGnd2 write FBackGnd2;
  62.   published
  63.     { published declarations }
  64.     property Image: TBitmap read FImage write SetImage;
  65.     property Color: TColor read FColor write SetColor default clBlack;
  66.     property Center: boolean read FCenter write SetCenter default true;
  67.     property Stretch: boolean read FStretch write SetStretch default false;
  68.     property Gradient: boolean read FGradient write SetGradient default false;
  69.     property BeforeSprtMove: TNotifyEvent read FBeforeSprtMove write SetBeforeSprtMove;
  70.     property AfterSprtMove: TNotifyEvent read FAfterSprtMove write SetAfterSprtMove;
  71.     property Align;
  72.     property Visible;
  73.     property OnClick;
  74.   end;
  75.  
  76. procedure Register;
  77.  
  78. implementation
  79.  
  80. {$IFDEF WIN32}
  81.   {$R SPRITEBX.D32}
  82. {$ELSE}
  83.   {$R SPRITEBX.D16}
  84. {$ENDIF}
  85.  
  86. constructor TSpriteBox.Create(AOwner: TComponent);
  87. begin
  88.   inherited Create(AOwner);
  89.   ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents,
  90.     csOpaque, csDoubleClicks];
  91.   FImage := TBitMap.Create;
  92.   FBackGnd1 := TBitMap.Create;
  93.   FBackGnd2 := TBitMap.Create;
  94.   FCenter := true;
  95.   FColor := clBlack;
  96.   FStretch := false;
  97.   FGradient := false;
  98.   FImage.OnChange := HasChanged;
  99.   Width := 105;
  100.   Height := 105;
  101. end;
  102.  
  103. destructor TSpriteBox.Destroy;
  104. begin
  105.   FImage.Free;
  106.   FBackGnd1.Free;
  107.   FBackGnd2.Free;
  108.   inherited Destroy;
  109. end;
  110.  
  111. procedure TSpriteBox.SetImage(AImage: TBitmap);
  112. begin
  113.   {Copy BackGnd image data from source bitmap}
  114.   FImage.Assign(AImage);
  115. end;
  116.  
  117. procedure TSpriteBox.SetColor(Value: TColor);
  118. begin
  119.   if FColor <> Value then
  120.   begin
  121.     FColor := Value;
  122.     DrawBMP;
  123.   end;
  124. end;
  125.  
  126. procedure TSpriteBox.SetCenter(Value: boolean);
  127. begin
  128.   if FCenter <> Value then
  129.   begin
  130.     FCenter := Value;
  131.     DrawBMP;
  132.   end;
  133. end;
  134.  
  135. procedure TSpriteBox.SetStretch(Value: boolean);
  136. begin
  137.   if FStretch <> Value then
  138.   begin
  139.     FStretch := Value;
  140.     DrawBMP;
  141.   end;
  142. end;
  143.  
  144. procedure TSpriteBox.SetGradient(Value: boolean);
  145. begin
  146.   if FGradient <> Value then
  147.   begin
  148.     FGradient := Value;
  149.     DrawBMP;
  150.   end;
  151. end;
  152.  
  153. procedure TSpriteBox.SetBeforeSprtMove(Value: TNotifyEvent);
  154. begin
  155.   FBeforeSprtMove := Value;
  156. end;
  157.  
  158. procedure TSpriteBox.SetAfterSprtMove(Value: TNotifyEvent);
  159. begin
  160.   FAfterSprtMove := Value;
  161. end;
  162.  
  163. procedure TSpriteBox.Loaded;
  164. begin
  165.   { always call the inherited Loaded first! }
  166.   inherited Loaded;
  167.   DrawBMP;
  168. end;
  169.  
  170. function TSpriteBox.GetPalette: HPALETTE;
  171. begin
  172.   Result := TBitmap(FBackGnd1).Palette;
  173. end;
  174.  
  175. procedure TSpriteBox.HasChanged(Sender: TObject);
  176. begin
  177.   DrawBMP;
  178. end;
  179.  
  180. procedure TSpriteBox.GradientFill(Color1, Color2: TColor);
  181. var
  182.   RGBFrom: array[0..2] of byte;
  183.   RGBDiff: array[0..2] of integer;
  184.   ColorBand: TRect;
  185.   I: integer;
  186.   R,G,B: Byte;
  187. begin
  188.   { extract from RGB values}
  189.   RGBFrom[0] := GetRValue(ColorToRGB(Color1));
  190.   RGBFrom[1] := GetGValue(ColorToRGB(Color1));
  191.   RGBFrom[2] := GetBValue(ColorToRGB(Color1));
  192.   { calculate difference of from and to RGB values}
  193.   RGBDiff[0] := GetRValue(ColorToRGB(Color2)) - RGBFrom[0];
  194.   RGBDiff[1] := GetGValue(ColorToRGB(Color2)) - RGBFrom[1];
  195.   RGBDiff[2] := GetBValue(ColorToRGB(Color2)) - RGBFrom[2];
  196.   { set color band's left and right coordinates}
  197.   ColorBand.Left := 0;
  198.   ColorBand.Right := Width;
  199.   for I := 0 to $100 do
  200.   begin
  201.     { calculate color band's top and bottom coordinates}
  202.     ColorBand.Top := MulDiv(I, Height, $100);
  203.     ColorBand.Bottom := MulDiv(I + 1, Height, $100);
  204.     { calculate color band color}
  205.     R := RGBFrom[0] + MulDiv(I, RGBDiff[0], $ff);
  206.     G := RGBFrom[1] + MulDiv(I, RGBDiff[1], $ff);
  207.     B := RGBFrom[2] + MulDiv(I, RGBDiff[2], $ff);
  208.     { select brush and paint color band}
  209.     FBackGnd1.Canvas.Brush.Color := RGB(R, G, B);
  210.     FBackGnd1.Canvas.FillRect(ColorBand);
  211.   end;
  212. end;
  213.  
  214. procedure TSpriteBox.DrawBMP;
  215. var
  216.   Dest: TRect;
  217. begin
  218.   { set size of BackGnd1 }
  219.   FBackGnd1.Width := Width;
  220.   FBackGnd1.Height := Height;
  221.   { set brush color }
  222.   FBackGnd1.Canvas.Brush.Color := FColor;
  223.   { fill BackGnd1.Canvas }
  224.   if FGradient then GradientFill(FColor,clBlack)
  225.     else FBackGnd1.Canvas.FillRect(ClientRect);
  226.   { if Image set then... }
  227.   if (FImage.Width <> 0) and (FImage.Height <> 0) then
  228.   begin
  229.     { ...set Dest values... }
  230.     if Stretch then
  231.       Dest := ClientRect
  232.     else if Center then
  233.       Dest := Bounds((Width - FImage.Width) div 2, (Height - FImage.Height) div 2,
  234.         FImage.Width, FImage.Height)
  235.     else
  236.       Dest := Rect(0, 0, FImage.Width, FImage.Height);
  237.   end;
  238.   { ...StretchDraw to BackGnd1.Canvas }
  239.   FBackGnd1.Canvas.StretchDraw(Dest, FImage);
  240.   { copy backgnd1 to backgnd2 }
  241.   FBackGnd2.Assign(FBackGnd1);
  242.   Invalidate;
  243. end;
  244.  
  245. procedure TSpriteBox.DrawSprite;
  246. var
  247.   i, OldLeft, OldTop: integer;
  248. begin
  249.   for i := 0 to ControlCount-1 do
  250.   begin
  251.     if (Controls[i] is TSprite) and (Controls[i] as TSprite).Enabled then
  252.     begin
  253.       with (Controls[i] as TSprite) do
  254.       begin
  255.         if Assigned(FBeforeSprtMove) then BeforeSprtMove(Controls[i]);
  256.  
  257.         OldLeft := SLeft;
  258.         OldTop := STop;
  259.  
  260.         MoveSprite;
  261.  
  262.         { Erase the old sprite in BackGnd2 }
  263.         BitBlt(BackGnd2.Canvas.Handle, OldLeft-2, OldTop-2, Width+2, Height+2,
  264.            BackGnd1.Canvas.Handle, OldLeft-2, OldTop-2, SrcCopy);
  265.  
  266.         { Draw the sprite at the new location in BackGnd2 }
  267.         BitBlt(BackGnd2.Canvas.Handle, SLeft, STop, Width, Height,
  268.            ANDImage.Canvas.Handle, 0, 0, SRCAND);
  269.         BitBlt(BackGnd2.Canvas.Handle, SLeft, STop, Width, Height,
  270.            ORImage.Canvas.Handle, 0, 0, SRCPAINT);
  271.  
  272.         { Copy a rectangle from BackGnd2 to reposition the sprite on the
  273.           canvas }
  274.         BitBlt(Canvas.Handle, OldLeft - 2, OldTop - 2, Width + 2, Height + 2,
  275.            BackGnd2.Canvas.Handle, OldLeft - 2, OldTop - 2, SrcCopy);
  276.  
  277.         if Assigned(FAfterSprtMove) then AfterSprtMove(Controls[i]);
  278.       end;
  279.     end;
  280.   end;
  281. end;
  282.  
  283. { Trap the Windows message requesting our size change,
  284.   let it, then redraw }
  285. procedure TSpriteBox.WMSize(var message: TWMSize);
  286. begin
  287.   inherited;
  288.   if message.SizeType in [SIZE_MAXHIDE,SIZE_MAXSHOW] then
  289.      Exit;  { Not our window that was resized }
  290.   DrawBMP;
  291. end;
  292.  
  293. procedure TSpriteBox.Paint;
  294. begin
  295.   Canvas.StretchDraw(ClientRect, FBackGnd1);
  296.   if not (csDesigning in ComponentState) then DrawSprite;
  297. end;
  298.  
  299. { register component on Misc page }
  300. procedure Register;
  301. begin
  302.   RegisterComponents('Misc', [TSpriteBox]);
  303. end;
  304.  
  305. end.